_Pragma("once");

#include <ctime>
#include <sstream>
#include <vector>

#include "ExtendDeviceType.h"
#include "DeviceStatisticInfo.h"
#include "StringUtility.h"
#include "common.h"
#include "Log.h"
#include"DummyChannel.h"


/**
 * 拓展通道上的设备
 * @author lizb
 */
class ExtendDevice {
public:
    ExtendDevice(DummyChannel& channel, const ExtendDeviceType& deviceType, const std::string& deviceActknowlege): mchannel(channel), mdeviceType(deviceType), mdeviceActknowlege(deviceActknowlege) {
        findTime = std::time(&findTime);
    }

    virtual ~ExtendDevice() {};

    virtual bool initialize() noexcept{
        return true;
    };



    virtual bool updateInformation(){
        return true;
    }

    //work with recheck
    virtual void update(const int& command, void* data, const Task* pTask) noexcept{
    }


    virtual bool activeUpdateInformation(){

             return true;
    }

    virtual ExtendDevice* getDevice(const ExtendDeviceType& deviceType);


    /**
     * 重新确认设备是否存在
     */
    virtual bool recheck() noexcept {
        std::string returnString;
        bool result = mdeviceActknowlege == check(mchannel, returnString);
        mdeviceStatisticInfo.setCheckStatus(result);

        return result;
    }

    static std::string& check(DummyChannel& channel, std::string& result);


    bool matchDevice(DummyChannel& channel, const std::string& deviceActknowlege){

        return mchannel == channel && mdeviceActknowlege == deviceActknowlege;
    }


    std::ostringstream& toString(std::ostringstream& output) {
        output << mdeviceType.name << " in ";
        mchannel.toString(output);
        return output;
    }


    DummyChannel& mchannel;
    const ExtendDeviceType& mdeviceType;//设备类型

    const std::string mdeviceActknowlege;

    std::string mversionString;

    std::time_t findTime;//发现该设备的时间

protected:

    bool activeUpdateForRecheck() noexcept;

    void afterCheck() {
        std::ostringstream outputStream;
        toString(outputStream);
        outputStream << ",check success times:" << mdeviceStatisticInfo.checkSuccessTimes << " fail times:" << mdeviceStatisticInfo.checkFailTimes;
        if (mdeviceStatisticInfo.continuousCheckFailTimes > mdeviceStatisticInfo.alarmThreshold) {
            outputStream << "continuousCheckFailTimes bigger than alarmThreshold, device disconnecting";
        }
        LOG_ERROR(outputStream.str().data());
        outputStream.str(StringUtility::EMPTY_STRING);
    }

    void afterInteraction() {
        std::ostringstream outputStream;
        toString(outputStream);
        outputStream << ",interaction success times:" << mdeviceStatisticInfo.interactionSuccessTimes << " fail times:" << mdeviceStatisticInfo.interactionFailTimes;
        if (mdeviceStatisticInfo.continuousInteractionFailTimes > mdeviceStatisticInfo.alarmThreshold) {
            outputStream << "continuousInteractionFailTimes bigger than alarmThreshold, device rechecking";
            recheck();
        }
        LOG_ERROR(outputStream.str().data());
        outputStream.str(StringUtility::EMPTY_STRING);
    }

    DeviceStatisticInfo  mdeviceStatisticInfo;
};


typedef  std::shared_ptr<ExtendDevice> ExtendDevicePtr;
typedef  std::weak_ptr<ExtendDevice> ExtendDeviceWeakPtr;


typedef std::vector<ExtendDeviceWeakPtr> ExtendDeviceWeakPtrs;
